'''
Created on Jan 7, 2011

@author: jackreilly
'''

from urllib2 import urlopen
from urllib import quote_plus
from BeautifulSoup import BeautifulStoneSoup as bss
from operator import itemgetter
from django.utils.simplejson import loads
import re

ytSearchString = 'http://gdata.youtube.com/feeds/api/videos?q=%s&orderby=viewCount&start-index=1&max-results=1&v=2&key=%s&alt=json'
    
lfmSearchString = 'http://ws.audioscrobbler.com/2.0/?method=track.search&track=%s&api_key=%s'
lfmSimilarString = 'http://ws.audioscrobbler.com/2.0/?method=track.getsimilar&artist=%s&track=%s&api_key=%s&autocorrect=1&limit=5'

track = 'MELANCHOLY HILL'
API_KEY = 'be485689ee193640df3efa76ac006bec'
YT_KEY = 'AI39si6IWAGDlDxxBmgpXL8OAQ718wpTSq03cD3IOkJknFLPWj6rhSVGXzYn1SH3mgmR0TsGWSLEa5rEVFnxCo5PvZpLZuXo6g'
ACCEPT_NSONGS = 2
ACCEPTABLE_SCORE = 1000

def constructSimilar(artist,track):
    return lfmSimilarString % (quote_plus(artist),quote_plus(track),API_KEY)

def constructSearch(song):
    return lfmSearchString % (quote_plus(song),API_KEY)

def constructYTSearch(song):
    return ytSearchString % (quote_plus('%s - %s' % (song[2],song[1])),YT_KEY)

def getBestMatch(song):
    xmlstuff =  bss(urlopen(constructSearch(song)).read())

    rank = 0
    songs = []
    for incident in xmlstuff('track'):
        rank+=1
        score = float(incident('listeners')[0].renderContents())/rank
        title = incident('name')[0].renderContents()
        artist = incident('artist')[0].renderContents()
        songs.append((score,title,artist))
    score = 0
    leadSong = None
    for song in songs:
        if song[0] > score:
            leadSong = song
            score = song[0]
    return leadSong

def getSimilarSongs(song):
    
    def similarSongs(leadSong):
        xmlstuff = bss(urlopen(constructSimilar(leadSong[2],leadSong[1])).read())
        songs = []
        for incident in xmlstuff('track'):
            try:
                score = int(incident('playcount')[0].renderContents())
            except:
                score = 100000
            title = incident('name')[0].renderContents()
            artist = incident('artist')[0]('name')[0].renderContents()
            songs.append((score,title,artist))
        if len(songs) < ACCEPT_NSONGS:
            return getSimilarSongs(song.replace(re.search(r'.*(\(.*\))',song).group(1),''))
        return sorted(songs, key=itemgetter(0), reverse=True)
    
    leadSong = getBestMatch(song)
    if (not leadSong) or (leadSong[0] < ACCEPTABLE_SCORE):
        try:
            return getSimilarSongs(song.replace(re.search(r'.*(\(.*\))',song).group(1),''))
        except:
            return []
    return similarSongs(leadSong)

def getYTTitle(song):
    ytinfo = loads(urlopen(constructYTSearch(song)).read())
    title = ytinfo['feed']['entry'][0]['title']['$t']
    id = ytinfo['feed']['entry'][0]['id']['$t'].split(':')[-1]
    thumb = ytinfo['feed']['entry'][0]['media$group']['media$thumbnail'][0]['url']
    return {
            'title':title,
            'id':id,
            'thumb':thumb
            }

def getRelatedVideos(song):
    songs =getSimilarSongs(song)
    videos = []
    for song in songs:
        videos.append(getYTTitle(song))
    return videos
